// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Gunnar Ritter

#include "config/applemail.h"

#include <QtCore/QDir>

#include "util/common.h"
#include "util/protocol.h"
#include "util/provider.h"

namespace popdiag {

static QString GetPlistPath() {
  QDir home = QDir::home();
  return home.filePath("Library/Preferences/com.apple.mail.plist");
}

AppleMail::AppleMail() {
}

AppleMail::~AppleMail() {
}

bool AppleMail::CheckConfiguration(VerificationSet *out) const {
  AppleMailPlist plist;
  if (plist.Read(GetPlistPath()) == false)
    return false;
  for (int i = 0; i < plist.mail_accounts().size(); ++i) {
    const struct AppleMailPlist::MailAccount *acc =
        &plist.mail_accounts().at(i);
    if (acc->AccountType != "POPAccount" && acc->AccountType != "IMAPAccount")
      continue;
    AppleMailInspection *result = new AppleMailInspection(
        acc->AccountName,
        acc->AccountType == "POPAccount" ?
          AppleMailInspection::SERVERTYPE_POP :
          AppleMailInspection::SERVERTYPE_IMAP);
    result->Recalculate("");
    out->append(result);
  }
  return true;
}

QString AppleMail::program_name() const {
  return tr("Apple Mail", "Email reader program name");
}

AppleMailInspection::AppleMailInspection(const QString &account_name,
                                         enum ServerType server_type)
    : account_name_(account_name) {
  server_type_ = server_type;
}

void AppleMailInspection::Recalculate(const QString &email) {
  email_ = email.toLower();
  ClearLog();
  StartLogDetails();
  faults_.clear();
  LogDetails("Program", true, "Apple Mail");

  // We have to read the plist again here to catch the case when
  // the user has clicked the retest button.
  AppleMailPlist plist;
  if (plist.Read(GetPlistPath()) == false) {
    LogDetails("Read Plist", false, plist.error_message());
    faults_.append(Fault(PROFILE_NOT_UNDERSTOOD, plist.error_message()));
    return;
  }
  const struct AppleMailPlist::MailAccount *account = NULL;
  for (int i = 0; i < plist.mail_accounts().size(); ++i) {
    account = &plist.mail_accounts().at(i);
    if (account->AccountName == account_name_)
      break;
  }
  if (account == NULL) {
    LogDetails("Find Account", false, "Account disappeared during processing");
    faults_.append(Fault(PROFILE_NOT_UNDERSTOOD,
                         "Account disappeared during processing"));
    return;
  }

  LogDetails("AccountsVersion", true,
             QString::number(plist.accounts_version()));
  set_program_name(tr("Apple Mail"));
  set_program_code("am");  // do not translate this
  set_profile_name(account_name_);
  LogDetails("Profile", true, account_name_);
  set_is_default_program(true);

  set_display_name(account->FullUserName);
  set_display_email(account->EmailAddresses.at(0));

  InitProtocolDependentValues();

  incoming_server_name_ = account->Hostname;
  incoming_user_name_ = account->Username;
  incoming_socket_type_ = account->SSLEnabled ? SSL : PLAINTEXT;
  incoming_port_ = account->PortNumber;
  leave_on_server_ = account->DeletionPolicy != "RightAway";

  CheckIncomingSettings();

  bool found_our_smtp = false;
  for (int j = 0; j < plist.delivery_accounts().size(); ++j) {
    const struct AppleMailPlist::DeliveryAccount *daccount =
        &plist.delivery_accounts().at(j);
    if (account->SMTPIdentifier ==
        daccount->Hostname + ":" + daccount->Username) {
      found_our_smtp = true;
      smtp_username_ = daccount->Username;
      smtp_email_ = email_;
      smtp_use_auth_ = daccount->ShouldUseAuthentication;
      switch (daccount->SSLEnabled) {
        case true:
          switch (daccount->SecurityLayerType) {
            case 2:
              smtp_socket_type_ = SSL;
              break;
            case 3:
              smtp_socket_type_ = TLS;
              break;
            default:
              smtp_socket_type_ = PLAINTEXT;
          }
          break;
        case false:
          smtp_socket_type_ = PLAINTEXT;
      }
    }
  }
  if (!found_our_smtp) {
    LogDetails("SMTP Server", false, "No matching smtp server found");
    faults_.append(Fault(SMTP_SERVER, ""));
  } else {
    CheckOutgoingSettings();
  }
}

}  // namespace popdiag
